#include  "crossplat_def.h"
#include "dvr_server_udp.h"
#include "dvr_cmd.h"
#ifdef _WIN32
//#include <winsock2.h>
//#include<ws2tcpip.h>
#else
#endif
#include "cross_com.h"

CUdpSvrSocket::CUdpSvrSocket()
{
	m_rcvBuf = NULL;
	m_outBuf = NULL;
	if(NULL == m_rcvBuf)
	{
		m_rcvBuf_sz = SIZE_KB(4);// SIZE_KB(16);
		m_rcvBuf = new unsigned char[m_rcvBuf_sz];
	}
	m_client_max = 16;
	m_send_sz = SIZE_KB(32);

	m_outBuf  = new unsigned char[m_send_sz];
	m_sock    = 0;
	memset(m_rcvBuf,0,SIZE_KB(4));
	memset(m_outBuf,0,m_send_sz);

}

CUdpSvrSocket::~CUdpSvrSocket()
{

}
int CUdpSvrSocket::Init(int send_buf_sz,int portNum)
{
	if(NULL == m_rcvBuf)
	{
		m_rcvBuf = new unsigned char[SIZE_KB(4)];
	}
	if(NULL == m_outBuf)
	{
		m_send_sz = SIZE_KB(32);
		m_outBuf  = new unsigned char[send_buf_sz];
	}
	memset(m_rcvBuf,0,SIZE_KB(4));
	memset(m_outBuf,0,m_send_sz);
#ifdef _WIN32
	WORD sockVersion = MAKEWORD(2,2);
	WSADATA wsaData;
	static bool bInit = false;

	if(!bInit)
	{
		if(WSAStartup(sockVersion, &wsaData)!=0)
		{
		//	return 0;
		}
		bInit = true;
	}
	//�����׽���
	m_sock = socket(AF_INET, SOCK_DGRAM, 0);
	if (m_sock == INVALID_SOCKET)
	{
		printf("socket error !");
		return 0;
	}
#else
	m_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if (m_sock == INVALID_SOCKET)
	{
		printf("socket error !");
		return 0;
	}
#endif
	//��IP�Ͷ˿�
	sockaddr_in sin;
	sin.sin_family = AF_INET;
	sin.sin_port = htons(portNum);
#ifdef _WIN32
	sin.sin_addr.s_addr = htonl(INADDR_ANY);
#else
    sin.sin_addr.s_addr = htonl(INADDR_ANY);
#endif // _WIN32
	int on = 1;
	if (bind(m_sock, (struct sockaddr *)&sin, sizeof(sin)) == -1)
	{
		printf("bind error !");
	}

#ifndef _WIN32
	int ret = setsockopt(m_sock,SOL_SOCKET,SO_REUSEADDR,(const char*)&on,sizeof(on));
	if(ret < 0)
	{
		printf("set sockopt fail.!");
	}
#endif


	return 0;
}


int CUdpSvrSocket::Start()
{
	//m_dataThdID = CreateThread((cross_start_routine)CmdServerUdpProcThread, (void *)this, NULL, SIZE_128KB);
	m_thd = std::thread(&CUdpSvrSocket::CmdServerUdpProcThread, this);
	m_thd.detach();
	return 0;
}

int  CUdpSvrSocket::CmdServerUdpProcThread(void *pParam)
{
	int ret = 0;

	CUdpSvrSocket * pTask = (CUdpSvrSocket *)pParam;

	static bool bRun = false;
	if (bRun)
	{
		return -1;
	}

	bRun = true;

	pTask->ListenProc();

	bRun = false;

	TRACE("++++End Start ListenProcThread");

	return ret;
}


int CUdpSvrSocket::GetIpaddrInfo(SOCKET fd, sockaddr_in  socke_add )
{
	return 0;
}

int CUdpSvrSocket::IoctrlSock(SOCKET sock, long cmd,unsigned long * argp)
{
	int ret = 0;
#ifdef _WIN32
	ret = ioctlsocket(sock,cmd,argp);
#else
	ret = ioctl(sock,cmd,&argp);
#endif
	return ret;
}
void CUdpSvrSocket::CloseSock(SOCKET sock)
{
#ifdef _WIN32
	closesocket(sock);
#else
	close(sock);
#endif
}



#define BUF_SIZE  1024
#define SOCK_SIZE 1024

#ifdef  _WIN32
int CUdpSvrSocket::ListenProc()
{

	CDVRCmd dvrcmd;

	struct timeval tv_out;
	tv_out.tv_sec = 5;//�ȴ�5��
	tv_out.tv_usec = 0;

	struct sockaddr_in from;//�ͻ��˵�ַ��ؽṹ��
	int fromlen = sizeof(from);
	int selright = 0;
	int ret = 0;
	int recv_len = 0;
	while (true)
	{
// 		selright = select(m_sock + 1, &readfds, NULL, NULL, &tv_out);
// 		if (selright <= 0)//Ϊ0ʱΪ��ʱ��С��0ʱΪ��������������Է��������룬��������ͬ�Ĵ���
// 		{
// 		//	printf("����ʧ��");
// 			CrossSleep(50);
// 			continue;
// 		}
// 		else
// 		{
	     	recv_len = recvfrom(m_sock, (char *)m_rcvBuf, 256, 0, (struct sockaddr*)&from, &fromlen);
			if (recv_len != SOCKET_ERROR)//�������ܿͻ��˵�����
			{
				//printf("���ӳɹ�����ʼ��������\n");

				dvrcmd.AttachSocket(m_sock, (struct sockaddr*)&from, fromlen);

				ret = dvrcmd.AnalysisCmd(m_rcvBuf, recv_len);
			}
			else
			{
				int err = GetLastError();

					//	printf("recieve data fail! errno %d \n", err);
				CrossSleep(50);
				continue;

			}
	//	}

	}


	CloseSock(m_sock);
	return 0;
}
#else
int CUdpSvrSocket::ListenProc()
{
	SOCKET clntSock;
	sockaddr_in clntAddr;

	socklen_t clntAddrSz;
	int ret = 0;
	fd_set  copyRead;
	struct timeval  tm;
	int sockNum = 0;
	unsigned long ul = 1;
	//����socks�������е�Ԫ��������Ч��socket
	for (int i = 0; i < SOCK_SIZE; i++)
	{
		m_socks[i] = INVALID_SOCKET;
	}
	sockNum += 1;

	m_socks[0] = m_sock;
	FD_ZERO(&m_fds);
	FD_SET(m_sock, &m_fds);
	tm.tv_sec = 5000;
	tm.tv_usec = 0;
	int selResult;
	socklen_t len;
	CDVRCmd dvrcmd;
	char buf[BUF_SIZE];
	len = sizeof(clntAddr);



	while (1)
	{

		FD_ZERO(&m_fds);
		FD_SET(m_sock, &m_fds);
		copyRead = m_fds;
		selResult = select(m_sock + 1, &copyRead, NULL, NULL, &tm);

		if (selResult == -1)
		{
			CrossSleep(100);
			puts("select error");
		}
		else if (selResult == 0)
		{
			CrossSleep(100);
			continue;
		}
		else
		{
			ret = recvfrom(m_sock, (char *)m_rcvBuf, m_rcvBuf_sz, 0, (struct sockaddr*)&clntAddr, &len);
			if (ret == -1)
			{

				int err = errno;
				printf("recieve data fail! errno %d \n", err);
				return 0;
			}

			dvrcmd.AttachSocket(m_sock, (struct sockaddr*)&clntAddr, len);

			ret = dvrcmd.AnalysisCmd(m_rcvBuf, m_rcvBuf_sz);

		}

	}

	CloseSock(m_sock);
	return 0;
}
#endif

